<?php
/**
 * i18n
 *
 * @version:	0.0
 * @package:	global
 * @author:	alex_ez
 * @created:	25.01.2010 16:16
 *
 * @copyright:	(c) 2010 alex <qfox@ya.ru> yaroshevich aka alex_ez. All rights reserved.
 */


class i18n_admin_controller extends admin_controller
{
	static public function get_menu_items( )
	{
		//return json::decode( '{"i18n":{"text":"i18n","group":"Система"}}' );
	}
	
	public function on_start( )
	{
		$this ->visitor = visitor::instance( );
		$this ->visitor ->need_auth( 'admin' );
		$this ->frame = 'admin/!index.tpl';
		
		$this ->model = new i18n_labels( );
		$this ->languages = new i18n_languages( );
	}
	
	
	public function page_index( $p, $o )
	{
		$r = array( );
		//$r = array( 'list' => $this ->model ->by( array( ), 'tag' ) );
		$r['title'] = 'Labels';
		
		$r['languages'] = $this ->languages ->by( array( 'state' => 'active' ), 'tag+' );
		$r['all_languages'] = $this ->languages ->by( '', 'tag+' );
		
		foreach( $this ->model ->by( array( ), 'tag+,language_id+' ) as $label_id => $label )
		{
			$r['items'][ $label['tag'] ][ $label['language_id'] ] = $label;
		}
		
		return $r;
	}
	
	public function ajax_rpc( )
	{
		$r = Request::instance( );
		$action = (string)_::pick( $r->p_action );
		if( strpos( ',add,edit,remove,refresh,', ','.$action.',' ) === false )
			return array( 'error' => 'Method not supported' );
		
		$data = $r->p_data;
		if( !@$data['tag'] ) return array( 'error' => 'Internal error #0' );
		
		$languages = $this ->languages ->by( array( 'state' => 'active' ) );
		bc::log( $data, 'data' );
		switch( $action )
		{
		case 'add':
			if( !@$data['new'] ) return array( 'error' => 'Internal error #1' );
		case 'edit':
			$tag = $data['tag'];
			foreach( array_keys( $languages ) as $lid )
			if( isset( $data[$lid] ) && is_array( $data[$lid] ) && isset( $data[$lid]['value'] ) )
			{
				$l = $data[$lid];
				$l['language_id'] = $lid;
				$l['tag'] = $tag;
				$this ->model ->add( $l, 2 );
			}
			break;
		case 'remove':
			$tag = $data['tag'];
			$ids = array_keys( $this ->model ->by( array( 'tag' => $tag ) ) );
			foreach( $ids as $id )
				$this ->model ->remove( $id );
			break;
		case 'refresh':
			
			break;
		}
		
		return array( );
	}
	
	private function getLabelId( $language_id, $tag )
	{
		$w = array( 'language_id' => $language_id, 'tag' => $tag );
		$items = $this ->model ->by( $w );
		$item = reset( $items );
		if( !$item )
		{
			$w['value'] = '';
			$item = $this ->model ->add( $w );
		}
		
		return $item['id'];
	}

	public function page_Languages( $p, $o )
	{
		$r = array( );
		
		$r['title'] = 'Languages list';
		foreach( $this ->languages ->by( '', 'tag+' ) as $l )
		if( $l['id'] != 0 )
		{
			$l['dl'] = sprintf( '<a href="../export/?language=%s" class="ibutton down" title="%s"> </a>', $l['tag'], 'Download db data as PO-file' );
			$l['dl'].= sprintf( '<a href="../export/?language=%s&source=file" class="ibutton down" title="%s"> </a>', $l['tag'], 'Download PO-file data as is');
			$l['up'] = sprintf( '<a href="../import/?language=%s" class="ibutton up" title="%s"> </a>', $l['tag'], 'Upload to db your PO-file');
			$l['st'] = sprintf( '<a href="../compile/?language=%s" class="ibutton apply" title="%s"> </a>', $l['tag'], 'Compile labels into PO- & MO-files' );
			$r['items'][] = $l;
		}
		$r['template'] = '__list.tpl';
		
		$this ->meta = array( 'title' => $r['title'] );
		
		return $r;
	}
	
	public function page_compare( $p, $o )
	{
		$r = array( );
		$r['languages'] = $this ->languages ->by( array( 'state' => 'active' ) );
		
		$request = request::instance( );
		
		if( !$request ->g_language )
		{
			$language = reset( $r['languages'] );
			response::instance( ) ->moved( '?language='.$language['tag'] );
		}
		
		$language = $this ->languages ->byTag( $request ->g_language );
		
		/* 4tr: hello, guys */
		$r['title'] = 'Comparing label databases' . ' — '.$language['name'];
		
		$po = new po( );
		
		$locale = sprintf( '%s.%s', $language['tag'], $language['charset'] );
		$path = $po ->getPath( $locale );
		if( !file_exists( $path ) )
		{
			$r['message'] = 'Not compiled.';
			return $r;
		}
		
		$po ->load( $path );
		
		$list1 = $this ->reformat( $po ->entries, $language['id'] );
		$list1tags = _a::flat( $list1, 'tag', '$' );
		$list2 = $this ->model ->by( array( 'language_id' => $language['id'] ) );
		$list2tags = _a::flat( $list2, 'tag', '$' );
		
		$intersectTags = array_intersect_key( $list1tags, $list2tags );
		
		$list = array( );
		foreach( array_keys( $intersectTags ) as $k )
		{
			$poe = $list1[$list1tags[$k]];
			$dbe = $list2[$list2tags[$k]];
			$diff = array_diff_assoc( $poe, $dbe );
			$id = $dbe['id'];
			
			$list[$id] = $dbe;
			$list[$id]['diff'] = $diff;
		}
		
		$listpo = array( );
		foreach( array_diff_key( $list1tags, $intersectTags ) as $tag => $id )
			$listpo[] = $list1[$id];
		
		$listdb = array( );
		foreach( array_diff_key( $list2tags, $intersectTags ) as $tag => $id )
			$listdb[] = $list2[$id];
		
		$r += compact( 'list', 'listpo', 'listdb' );
		
		$this ->meta = array( 'title' => $r['title'] );
		
		return $r;
	}
	
	public function page_export( $p, $o )
	{
		$request = request::instance( );
		$response = response::instance( );
		
		$language = $this ->languages ->byTag( $request ->g_language );
		if( !$language )
			response::instance( ) ->moved( '../languages/' );
		
		$po = new po( );
		
		$source = _::pick( $request ->g_source, 'db' );
		$locale = sprintf( '%s.%s', $language['tag'], $language['charset'] );
		
		// urr
		$response ->charset = 'utf-8';
		$response ->contentType = 'application/x-gettext';
		$response ->contentDisposition = sprintf( '%s-%s-%s-%s.po', date('Ymd\THi'), HOST, $source, $language['tag'] );
		
		switch( $source )
		{
		case 'db':
			$listtags = $this ->model ->getTagsBy( '' );
			$list = $this ->model ->by( array( 'language_id' => $language['id'] ) );
			
			$diff = array_diff( array_keys( $listtags ), _a::flat( $list, '$', 'tag' ) );
			foreach( $diff as $v )
			{
				$adde = $listtags[$v];
				foreach( range( 0, 6 ) as $n ) unset( $adde['value'.($n>0?$n:'')] );
				$adde['value'] = (substr($language['tag'],0,2)=='en')?$adde['tag']:'';
				$list[] = $adde;
			}
			//var_dump( $list );
			
			$list = $this ->reformat( $list, $language['id'], true );
			
			echo $po ->render( $list, array( ), $language );
			die;
		case 'file':
			$path = $po ->getPath( $locale );
			if( !file_exists( $path ) || !is_readable( $path ) )
			{
				$response ->contentType = 'text/plain';
				$response ->contentDisposition = null;
				die( 'File not exists or not readable' );
			}
			
			echo file_get_contents( $path );
			die;
			break;
		default:
			break;
		}
		
		response::instance( ) ->moved( '../' );
		
		return '';
	}

	public function page_import( $p, $o )
	{
		$request = request::instance( );
		if( !$request ->g_language )
			response::instance( ) ->moved( '../languages/' );
		$language = $this ->languages ->byTag( $request ->g_language );
		if( !$language )
			response::instance( ) ->moved( '../languages/' );
		
		$r['language'] = $language;
		$r['title'] = 'Import PO-file to database';
		$this ->meta = array( 'title' => $r['title'] );
		
		$file = $request ->f_po;
		if( $file['error'] ) $r['error'] = 'Error while file uploading 5';
		if( !$file || $file['error'] ) return $r;
		
		
		$po = new po( );
		
		$locale = sprintf( '%s.%s', $language['tag'], $language['charset'] );
		
		$path = $po ->getPath( $locale );
		$tpath = $path.'-temp';
		$dir = pathinfo( $path, PATHINFO_DIRNAME );
		
		if( !file_exists( $dir ) ) @mkdir( $dir, 0750, 1 );
		if( !is_writable( $dir )
		 /*|| !is_writable( $path )*/ )
			{ $r['error'] = 'Error while file uploading'; return $r; }
		if( !move_uploaded_file( $file['tmp_name'], $tpath ) )
			{ $r['error'] = 'Error while file uploading 33'; return $r; }
		
		
		$po ->load( $tpath );
		$list = $this ->reformat( $po ->entries, $language['id'] );
		
		$listtags = _a::flat( $list, 'tag', '$' );
		$listdb = $this ->model ->by( array( 'language_id' => $language['id'], 'tag' => array_keys( $listtags ) ) );
		
		$edited = 0;
		foreach( $listdb as $id => $dbe )
		{
			$k = $listtags[$dbe['tag']];
			$poe = $list[$k];
			$diff = array_diff( $poe, $dbe );
			unset( $diff['id'] );
			
			unset( $list[$k] );
			if( empty( $diff ) )
				continue;
			
			$edited++;
			$this ->model ->edit( $id, $diff );
		}
		
		foreach( $list as $k => $poe )
		{
			$edited += !!$this ->model ->add( $poe );
		}
		
		return sprintf( ngettext('Imported %s row', 'Imported %s rows', $edited), $edited );
	}



	public function page_compile( $p, $o )
	{
		$request = request::instance( );
		if( !$request ->g_language )
			response::instance( ) ->moved( '../languages/' );
		$language = $this ->languages ->byTag( $request ->g_language );
		if( !$language )
			response::instance( ) ->moved( '../languages/' );
		
		$r['language'] = $language;
		$r['title'] = ('Compiling database to PO-file');
		$this ->meta = array( 'title' => $r['title'] );
		$r['message'] = '';
		
		$po = new po( );
		
		$locale = sprintf( '%s.%s', $language['tag'], $language['charset'] );
		
		$path = $po ->getPath( $locale );
		$dir = pathinfo( $path, PATHINFO_DIRNAME );
		$tpath = $dir.'/'.date('YdmH-').pathinfo( $path, PATHINFO_BASENAME );
		$mopath = vsprintf( '%1$s/%4$s.mo', array_values( pathinfo( $path ) ) );
		$tmopath = $dir.'/'.date('YdmH-').pathinfo( $mopath, PATHINFO_BASENAME );
		
		if( !file_exists( $dir ) ) @mkdir( $dir, 0750, 1 );
		if( !is_writable( $dir ) || (file_exists( $path ) && !is_writable( $path )) )
			{ $r['error'] = ('Have no permitions'); return $r; }
		
		// backups
		if( file_exists( $path ) )
		{
			if( rename( $path, $tpath ) )
				$r['message'] .= sprintf( ('Current %s stored to backup: %s.'), ('PO-file'), $tpath )."\n";
		}
		if( file_exists( $mopath ) )
		{
			if( rename( $mopath, $tmopath ) )
				$r['message'] .= sprintf( ('Current %s stored to backup: %s.'), ('MO-file'), $tmopath )."\n";
		}
		
		
		$list = $this ->model ->by( array( 'language_id' => $language['id'] ) );
		$list = $this ->reformat( $list, $language['id'], true );
		
		$content = $po ->render( $list, array( ), $language );
		
		file_put_contents( $path, $content );
		$exec = sprintf( 'msgfmt -v -f "%s" -o "%s" 2>&1', escapeshellcmd($path), escapeshellcmd($mopath) );
		
		exec( $exec, $out );
		
		$r['message'] .= "\n".join( "\n", $out )."\n";
		
		if( !file_exists( $mopath ) )
			$r['message'] .= ('We have a problem with compiling MO-file');
		
		return $r;
	}
	
	
	// from po-format and back
	private function reformat( $list, $language_id = null, $back = false )
	{
		foreach( array_keys( $list ) as $e )
		if( !$back || $list[$e] )
		{
			$kv = array( 'references' => "\n", 'flags' => ",", 'x' => "\n" );
			
			foreach( $kv as $k => $v )
			if( isset( $list[$e][$k] ) )
			{
				$list[$e][$k] = $back ? explode( $v, $list[$e][$k] ) : join( $v, $list[$e][$k] );
				if( is_array( $list[$e][$k] ) ) $list[$e][$k] = array_filter( $list[$e][$k] );
			}
			
			if( !$back )
			{
				$values = $list[$e]['value'];
				unset( $list[$e]['value'] );
				foreach( $values as $k => $v )
					$list[$e]['value'.($k>0?$k:'')] = $v;
			}
			else
			foreach( range( 0, 6 ) as $k )
			{
				$ok = 'value'.($k>0?$k:'');
				if( !isset( $list[$e][$ok] ) ) continue;
				$v = $list[$e][$ok];
				unset( $list[$e][$ok] );
				$list[$e]['value'][$k] = $v;
			}
			
			if( !$back )
				$list[$e]['language_id'] = $language_id;
			else
				unset( $list[$e]['language_id'] );
		}
		
		return $list;
	}
}
